import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Hashtable;
import java.util.Map.Entry;
import java.util.Set;


public class IntegerEncoding {

	static final String DELIMITER = "\t";
	static int hashTableCounter = 0;
	
	public static void main(String[] args) {
		String inputFile = args[0];
		String inputMap = args[1];
		String output = args[2];
		String mapOuput = args[3];
		String columnsToEncode = args[4];
		String[] tmp = columnsToEncode.split(",");
		int[] columns = new int[tmp.length];
		int count = 0;
		for (String column: tmp) {
			columns[count] = Integer.parseInt(column);
			count++;
		}
		Hashtable<String, Integer> ht;
		if (inputMap.equals("null"))
			ht = new Hashtable<String, Integer>();
		else 
			ht = inputMap(inputMap);
		
    	try {
    		FileInputStream fstream = new FileInputStream(inputFile);
    		DataInputStream in = new DataInputStream(fstream);
    		BufferedReader br = new BufferedReader(new InputStreamReader(in));
    		PrintWriter writer = new PrintWriter(new FileWriter(output));
    		
    		String strLine;
    		int lineCount = 0;
    		while ((strLine = br.readLine()) != null) {
    			String line = "";
    			tmp = strLine.split(DELIMITER);
    			for (int i = 0; i < tmp.length; i++) {
    				String column = tmp[i];
    				if (inTheArray(i, columns)) {
    					line += getHashTableEntry(column, ht) + "\t";
    				}
    				else {
    					line += column + "\t";
    				}
    			}
    			line = line.substring(0, line.length() - 1) + "\n";
    			writer.print(line);
    			lineCount++;
    			if (lineCount % 10000 == 0)
    				System.out.println(lineCount + " lines are processed");
    		}
    		
    		in.close();
    		writer.close();
    		outputMap(mapOuput, ht);
    	} catch (Exception e) {
    		System.err.println("Error: " + e.getMessage());
    	}
	}
	
	private static boolean inTheArray(int a, int[] array) {
		for (int b : array)
			if (a == b)
				return true;
		
		return false;
	}
	
	private static int getHashTableEntry(String input, Hashtable<String, Integer> ht) {
		Integer entry = ht.get(input);
		if (entry == null) {
			ht.put(input, hashTableCounter);
			entry = hashTableCounter;
			hashTableCounter++;
		}
		return entry;
	}
	
	private static void outputMap(String map, Hashtable<String, Integer> ht) {
		Set<Entry<String, Integer>> set = ht.entrySet();
		
		try {
			PrintWriter writer = new PrintWriter(new FileWriter(map));
			for (Entry<String, Integer> entry: set) {
				writer.print(entry.getKey() + DELIMITER + entry.getValue() + "\n");
			}
			writer.close();
    	} catch (Exception e) {
    		System.err.println("Error: " + e.getMessage());
    	}
	}
	
	private static Hashtable<String, Integer> inputMap(String map) {
		Hashtable<String, Integer> ht = new Hashtable<String, Integer>();
		
		try {
    		FileInputStream fstream = new FileInputStream(map);
    		DataInputStream in = new DataInputStream(fstream);
    		BufferedReader br = new BufferedReader(new InputStreamReader(in));
    		
    		String strLine;
    		while ((strLine = br.readLine()) != null) {
    			String[] tmp = strLine.split(DELIMITER);
    			ht.put(tmp[0], Integer.parseInt(tmp[1]));
    		}
    		
    		in.close();
    	} catch (Exception e) {
    		System.err.println("Error: " + e.getMessage());
    	}
		
		return ht;
	}
}